﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;

using TheSharpFontViewer.Properties;

namespace TheSharpFontViewer
{
    public partial class MainForm
    {
        private readonly Settings AppSettings = new Settings();
        private readonly Dictionary<string, FontFamily> FontCollection = new Dictionary<string, FontFamily>();
        private readonly Dictionary<string, ListBoxItem> FolderCollection = new Dictionary<string, ListBoxItem>();

        public MainForm()
        {
            InitializeComponent();
        }

        #region Gui Events

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            if (AppSettings.Folders == null)
            {
                AppSettings.Folders = new StringCollection();
                AppSettings.Folders.Add("$SystemFolder");
                AppSettings.Save();
            }

            foreach (string folder in AppSettings.Folders)
            {
                AddFolder(folder);
            }

            for (int i = 1; i != 301; i++)
            {
                Font_Size_ComboBox.Items.Add(i);
            }

            Font_Size_ComboBox.SelectedIndex = AppSettings.FontSize;
        }

        private void Fonts_listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (Fonts_listBox.SelectedItem != null)
            {
                FontFamily TEMP_FontFamily;
                FontCollection.TryGetValue(Fonts_listBox.SelectedItem.ToString().Remove(0, "System.Windows.Controls.ListBoxItem: ".Length), out TEMP_FontFamily);
                Text_textBox.FontFamily = TEMP_FontFamily;
                Fonts_Selected_TextBlock.Text = Fonts_listBox.SelectedItem.ToString().Remove(0, "System.Windows.Controls.ListBoxItem: ".Length);
                try
                {
                    Fonts_Selected_Path_TextBlock.Text = new Uri(TEMP_FontFamily.Source).AbsolutePath;
                }
                catch (Exception)
                {
                    Fonts_Selected_Path_TextBlock.Text = "$SystemFolder";
                }
            }
        }

        private void Fonts_Search_TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            Fonts_listBox.Items.Filter = (FilterFonts);
        }

        private void Text_textBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            AppSettings.TestText = Text_textBox.Text;
            AppSettings.Save();
        }

        #region ToolBar

        private void Font_Size_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            AppSettings.FontSize = Font_Size_ComboBox.SelectedIndex;
            AppSettings.Save();

            Text_textBox.FontSize = (int) Font_Size_ComboBox.SelectedValue;
        }

        private void Font_Bold_Button_Click(object sender, RoutedEventArgs e)
        {
            if (Text_textBox.FontWeight !=
                FontWeights.Bold)
            {
                Text_textBox.FontWeight = FontWeights.Bold;
            }
            else
            {
                Text_textBox.FontWeight = FontWeights.Normal;
            }
        }

        private void Font_Italic_Button_Click(object sender, RoutedEventArgs e)
        {
            if (Text_textBox.FontStyle !=
                FontStyles.Italic)
            {
                Text_textBox.FontStyle = FontStyles.Italic;
            }
            else
            {
                Text_textBox.FontStyle = FontStyles.Normal;
            }
        }

        private void Font_Underline_Button_Click(object sender, RoutedEventArgs e)
        {
            if (Text_textBox.TextDecorations !=
                TextDecorations.Underline)
            {
                Text_textBox.TextDecorations = TextDecorations.Underline;
            }
            else
            {
                TextDecorationCollection _TextDecorationCollection = Text_textBox.TextDecorations.Clone();
                _TextDecorationCollection.Clear();
                Text_textBox.TextDecorations = _TextDecorationCollection;
            }
        }

        private void ManageFolders_Button_Click(object sender, RoutedEventArgs e)
        {
            ManageFolders _ManageFolders = new ManageFolders();
            _ManageFolders.Owner = this;
            _ManageFolders.ShowDialog();

            if (_ManageFolders.DialogResult.HasValue &&
                _ManageFolders.DialogResult.Value)
            {
                AppSettings.Reload();

                if (_ManageFolders.DeletedFolders.Count != 0)
                {
                    foreach (string folder in _ManageFolders.DeletedFolders)
                    {
                        RemoveFolder(folder);
                    }
                }

                if (_ManageFolders.AddedFolders.Count != 0)
                {
                    foreach (string folder in _ManageFolders.AddedFolders)
                    {
                        AddFolder(folder);
                    }
                }
            }
        }

        #endregion

        #endregion

        private void AddFolder(string path)
        {
            BackgroundWorker AddFolder_BackgroundWorker = new BackgroundWorker();
            AddFolder_BackgroundWorker.DoWork += (AddFolder_BackgroundWorker_DoWork);
            AddFolder_BackgroundWorker.RunWorkerAsync(path);

            SortFonts();
        }

        private void AddFolder_BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            if (e.Argument.ToString() == "$SystemFolder")
            {
                foreach (FontFamily fontFamily in Fonts.SystemFontFamilies)
                {
                    AddFont(fontFamily, fontFamily.Source, "$SystemFolder");
                }
            }
            else
            {
                if (Directory.Exists(e.Argument.ToString()))
                {
                    string[] _files = Directory.GetFiles(e.Argument.ToString(), "*.*", SearchOption.AllDirectories);

                    foreach (string file in _files)
                    {
                        foreach (FontFamily fontFamily in Fonts.GetFontFamilies(file))
                        {
                            foreach (string value in fontFamily.FamilyNames.Values)
                            {
                                AddFont(fontFamily, value, e.Argument.ToString());
                            }
                        }
                    }
                }
            }
        }

        private void RemoveFolder(string path)
        {
            StringCollection DeletedKeys = new StringCollection();

            foreach (KeyValuePair<string, ListBoxItem> pair in FolderCollection)
            {
                string _key = pair.Key;
                string _deletedkey = pair.Key;
                _key = _key.Remove(_key.LastIndexOf('#'));

                if (_key == path)
                {
                    FontCollection.Remove(pair.Value.Content.ToString());
                    Fonts_listBox.Items.Remove(pair.Value);
                    DeletedKeys.Add(_deletedkey);
                }
            }
            SortFonts();

            foreach (string deletedKey in DeletedKeys)
            {
                FolderCollection.Remove(deletedKey);
            }

            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart) delegate
            {
                Fonts_listBox.Items.Refresh();
                Fonts_Count_TextBlock.Text = "Fonts: " + Fonts_listBox.Items.Count;
            });
        }

        private void AddFont(FontFamily fontfamily, string fontname, string path)
        {
            Dispatcher.BeginInvoke(DispatcherPriority.Background, (ThreadStart) delegate
            {
                if (!FontCollection.ContainsKey(fontname))
                {
                    ListBoxItem _ListBoxItem = new ListBoxItem();
                    _ListBoxItem.Content = fontname;
                    _ListBoxItem.ToolTip = fontname;

                    if (path != "$SystemFolder")
                    {
                        _ListBoxItem.ToolTip += Environment.NewLine + new Uri(fontfamily.Source).AbsolutePath;
                    }
                    else
                    {
                        _ListBoxItem.ToolTip += Environment.NewLine + "$SystemFolder";
                    }

                    _ListBoxItem.FontFamily = fontfamily;

                    FontCollection.Add(fontname, fontfamily);
                    Fonts_listBox.Items.Add(_ListBoxItem);
                    FolderCollection.Add(path + "#" + Fonts_listBox.Items.Count, _ListBoxItem);

                    Fonts_Count_TextBlock.Text = "Fonts: " + Fonts_listBox.Items.Count;
                }
                else
                {
                    AddFont(fontfamily, fontname + "-", path);
                }
            });
        }

        private void SortFonts()
        {
            Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, (ThreadStart) delegate
            {
                SortDescription _SortDescription = new SortDescription("Content", ListSortDirection.Ascending);
                Fonts_listBox.Items.SortDescriptions.Add(_SortDescription);
            });
        }

        private bool FilterFonts(object filter)
        {
            ListBoxItem _ListBoxItem = filter as ListBoxItem;
            if (_ListBoxItem != null)
            {
                return (_ListBoxItem.Content.ToString().Contains(Fonts_Search_TextBox.Text));
            }
            else
            {
                return false;
            }
        }
    }
}
